// file:src/kernel/fs/fstype.c
// autor:jiangxinpeng
// time:2021.2.23
// copyright:(C) by jiangxinpeng,All right are reserved.

#include <os/fstype.h>
#include <os/fsal.h>
#include <os/fatfs.h>
#include <os/cdfs.h>
#include <os/fifo.h>
#include <os/driver.h>
#include <os/fs.h>
#include <os/spinlock.h>
#include <lib/list.h>
#include <lib/string.h>

// list head used to manage all support fs
// support a fsal to system
LIST_HEAD(fsal_list_head);

DEFINE_SPIN_LOCK(fstype_lock);

// init all support fs type
int FsTypeInit()
{
    list_init(&fsal_list_head);

    // register file system
    // fatfs
    FsTypeRegister(&fatfs_fsal);
    // cdfs
    // FsTypeRegister(&cdfs_fsal);
    // devfs
    FsTypeRegister(&devfs_fsal);
    // fifofs
    FsTypeRegister(&fifofs_fsal);

    KPrint("[fs] init fstype end\n");
    return 0;
}

// used to add a fstype to system
void FsTypeRegister(fsal_t *fsal)
{
    SpinLockDisInterrupt(&fstype_lock);
    list_add_tail(&fsal->list, &fsal_list_head);
    SpinUnlockEnInterrupt(&fstype_lock);
}

void FsTypeUnRegister(fsal_t *fsal)
{
    SpinLockDisInterrupt(&fstype_lock);
    list_del(&fsal->list);
    SpinUnlockEnInterrupt(&fstype_lock);
}

fsal_t *FsTypeFind(char *name)
{
    int i = 0;
    fsal_t *fsal;

    list_traversal_all_owner_to_next(fsal, &fsal_list_head, list)
    {
        if (!fsal->subtable)
        {
            // check fstype name
            if (!strcmp(fsal->name, name))
            {
                // return fsal point
                return fsal;
            }
        }
        else
        {
            // if have subtable,we need cmp subtable fs
            while (fsal->subtable[i] != NULL)
            {
                // cmp subtable fstype
                if (!strcmp(fsal->subtable[i], name))
                {
                    return fsal;
                }
                i++; // next subtable
            }
        }
    }
    return NULL;
}
